package com.xiaoyu.util2;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

@SuppressWarnings("rawtypes")
public class ClassUtil {
	
	public Class loadClass(String className) throws ClassNotFoundException {
		Class theClass = null;
		try {
			theClass = Class.forName(className);
		} catch (ClassNotFoundException e1) {
			try {
				theClass = Thread.currentThread().getContextClassLoader().loadClass(className);
			} catch (ClassNotFoundException e2) {
				theClass = super.getClass().getClassLoader().loadClass(className);
			}
		}
		return theClass;
	}
	
	@SuppressWarnings("unchecked")
	public static String[] getField(String className)
			throws ClassNotFoundException {
		Class classz = Class.forName(className);
		Field[] fields = classz.getFields();
		Field[] fieldz = classz.getDeclaredFields();

		Set set = new HashSet();
		for (Field f : fields) {
			set.add(f.getName());
		}
		for (Field f : fieldz) {
			set.add(f.getName());
		}
		return ((String[]) set.toArray(new String[0]));
	}

	@SuppressWarnings("unchecked")
	public static String[] getMethod(String className)
			throws ClassNotFoundException {
		Class classz = Class.forName(className);
		Method[] methods = classz.getMethods();
		Set set = new HashSet();
		if (methods != null) {
			for (Method f : methods) {
				set.add(f.getName());
			}
		}
		return ((String[]) set.toArray(new String[0]));
	}

	public static <T> T propertiesCopy(Object obj, Class<T> type) {
		return null;
	}

	public static <T> T propertiesCopyIgnore(Object obj, Class<T> type) {
		return null;
	}

	public static <T> T propertiesCopyIgnoreFilter(Object obj, Class<T> type,
			String IgnoreStr) {
		return null;
	}

	public static void setter(Object obj, String att, Object value, Class<?> type) {
		try {
			Method met = obj.getClass().getMethod("set" + initStr(att), new Class[] { type });
			met.invoke(obj, new Object[] { value });
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static void getter(Object obj, String att) {
		try {
			Method met = obj.getClass().getMethod("get" + initStr(att), new Class[0]);
			System.out.println(met.invoke(obj, new Object[0]));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public static String initStr(String old) {
		String str = old.substring(0, 1).toUpperCase() + old.substring(1);
		return str;
	}

	public static List<String> getClassName(String packageName, boolean childPackage) {
		List<String> fileNames = null;
		ClassLoader loader = Thread.currentThread().getContextClassLoader();
		String packagePath = packageName.replace(".", "/");
		URL url = loader.getResource(packagePath);
		if (url != null) {
			String type = url.getProtocol();
			if (type.equals("file")) {
				fileNames = getClassNameByFile(url.getPath(), null, childPackage);
			} else if (type.equals("jar")) {
				fileNames = getClassNameByJar(url.getPath(), childPackage);
			}
		} else {
			fileNames = getClassNameByJars(((URLClassLoader) loader).getURLs(),
					packagePath, childPackage);
		}
		if (null != fileNames) {
			List<String> temp = new ArrayList<String>();
			for (String t : fileNames) {
				t = t.substring(t.indexOf(packageName), t.length());
				temp.add(t);
			}
			fileNames = temp;
		}
		return fileNames;
	}

	@SuppressWarnings("unchecked")
	private static List<String> getClassNameByFile(String filePath, List<String> className, boolean childPackage) {
		List myClassName = new ArrayList();
		File file = new File(filePath);
		File[] childFiles = file.listFiles();
		for (File childFile : childFiles) {
			if (childFile.isDirectory()) {
				if (childPackage) {
					myClassName.addAll(getClassNameByFile(childFile.getPath(), myClassName, childPackage));
				}
			} else {
				String childFilePath = childFile.getPath();
				if (childFilePath.endsWith(".class")) {
					childFilePath = childFilePath.substring(childFilePath.indexOf("\\classes") + 9, childFilePath.lastIndexOf("."));
					childFilePath = childFilePath.replace("\\", ".");
					myClassName.add(childFilePath);
				}
			}
		}
		return myClassName;
	}

	@SuppressWarnings("unchecked")
	private static List<String> getClassNameByJar(String jarPath, boolean childPackage) {
		List myClassName = new ArrayList();
		String[] jarInfo = jarPath.split("!");
		String jarFilePath = jarInfo[0].substring(jarInfo[0].indexOf("/"));
		String packagePath = jarInfo[1].substring(1);
		try {
			JarFile jarFile = new JarFile(jarFilePath);
			Enumeration entrys = jarFile.entries();
			while (entrys.hasMoreElements()) {
				JarEntry jarEntry = (JarEntry) entrys.nextElement();
				String entryName = jarEntry.getName();
				if (entryName.endsWith(".class"))
					if (childPackage) {
						if (entryName.startsWith(packagePath)) {
							entryName = entryName.replace("/", ".").substring(0, entryName.lastIndexOf("."));
							myClassName.add(entryName);
						}
					} else {
						int index = entryName.lastIndexOf("/");
						String myPackagePath;
						if (index != -1) {
							myPackagePath = entryName.substring(0, index);
						} else {
							myPackagePath = entryName;
						}
						if (myPackagePath.equals(packagePath)) {
							entryName = entryName.replace("/", ".").substring(0, entryName.lastIndexOf("."));
							myClassName.add(entryName);
						}
					}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return myClassName;
	}

	private static List<String> getClassNameByJars(URL[] urls, String packagePath, boolean childPackage) {
		List<String> myClassName = new ArrayList<String>();
		if (urls != null) {
			for (int i = 0; i < urls.length; ++i) {
				URL url = urls[i];
				String urlPath = url.getPath();
				if (urlPath.endsWith("classes/")) {
					continue;
				}
				String jarPath = urlPath + "!/" + packagePath;
				myClassName.addAll(getClassNameByJar(jarPath, childPackage));
			}
		}
		return myClassName;
	}
	
	public static void main(String[] args) {
		try {
			String [] strArray = ClassUtil.getField("com.xiaoyu.ftp.FileAttr");
			for(String s:strArray){
				System.out.println(s);
			}
			System.out.println("==============分隔符==============");
			String [] strArray1 = ClassUtil.getMethod("com.xiaoyu.ftp.FileAttr");
			for(String s:strArray1){
				System.out.println(s);
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
}